<?php

namespace app\result;

use app\model\user\Cashflows;
use app\model\user\User;
use app\model\user\UserPushSetting;

class PushResult extends BaseResult
{
    //推送设置
    public function push_setting($user_id, $arg): array
    {
        $has = (new UserPushSetting())->data_get(['user_id' => $user_id]);
        if (request()->isGet()) {
            $has['day_set'] = boolval($has['day_set'] ?? 0);
            $has['week_set'] = boolval($has['week_set'] ?? 0);
            $has['month_set'] = boolval($has['month_set'] ?? 0);
            $has['year_set'] = boolval($has['year_set'] ?? 0);
            return self::success_return('success', $has);
        }
        $baseData = [
            'user_id' => $user_id,
            'day_set' => $arg['day_set'] ?? 0,
            'week_set' => $arg['week_set'] ?? 0,
            'month_set' => $arg['month_set'] ?? 0,
            'year_set' => $arg['year_set'] ?? 0,
        ];
        if ($has) {
            $res = (new UserPushSetting())->data_update(['user_id' => $user_id], $baseData);
        } else {
            $res = (new UserPushSetting())->data_add($baseData);
        }
        return $this->success_return('设置成功');
    }

    /**
     * 账单推送
     * @param string $type //day|week|month|year
     * @return array
     */
    public function push_bill(string $type = 'day'): array
    {
        $fieldSet = $type . '_set';
        $userIds = (new UserPushSetting())->data_list_nopage([$fieldSet => 1], 'user_id');
        if (!$userIds) {
            return self::success_return('没有需要推送的用户');
        }
        $userIds = array_column($userIds, 'user_id');

        $model = new Cashflows();
        $msgResult = new UserMsgResult();
        switch ($type) {
            case 'day':
            case 'week':
            case 'month':
            case 'year':
                $title = 'day' === $type ? '日账单' : ('week' === $type ? '周账单' : ('month' === $type ? '月度账单' : '年度账单'));
                $this->format_data($model, $userIds, $type, $title, $msgResult);
                break;
            default:
                return self::error_return('参数错误');
        }
        return $this->success_return($title . ':success');
    }

    /**
     * 格式化数据并推送消息
     * @param $model
     * @param $userIds
     * @param $type
     * @param $title
     * @param $msgResult
     * @param $br
     */
    private function format_data($model, $userIds, $type, $title, $msgResult)
    {
        $field = 'type,user_id,sum(IF(type=10,amount,0)) as income,sum(IF(type=20,amount,0)) as outcome';
        $dates = $this->get_dates_by_type($type);
        $data = $model->data_list_nopage([['user_id', 'in', $userIds], ['date', 'between', [$dates['start'], $dates['end']]]], $field, '', 'user_id');
        if ($data) {
            $modelUser = new User();
            foreach ($data as $v) {
                $v['income'] = !empty($v['income']) ? $v['income'] : '0.00';
                $v['outcome'] = !empty($v['outcome']) ? $v['outcome'] : '0.00';
                $this->calculate_growth($model, $v, $dates, $type);
                $msg = $this->build_message($v, $dates, $title, $type);
                $msgData = [
                    'title' => $title . ($type == 'day' ? '【' . $dates['start'] . '】' : '【' . $dates['start'] . '~' . $dates['end'] . '】'),
                    'content' => $msg,
                    'path_info' => [
                        'title' => '账单列表',
                        'path' => '/pages/index/list',
                        'jump_type' => 'inner',//inner=内页，tab=底部导航，link=外链
                    ],
                ];
                $msgResult->add($v['user_id'], $msgData);
                $email = $modelUser->get_value(['user_id' => $v['user_id']], 'email');
                if ($email) {
                    bs_log([
                        'title' => $msgData['title'],
                        'sub_title' => $title,
                        'user_id' => $v['user_id'],
                        'email' => $email
                    ], 'bill_send_email_info', 'send_email.log');
                    //队列不存放邮件内容，只存放key，通过key获取邮件内容
                    $send_bill_key = 'send_bill_' . $v['user_id'] . '_' . $type . '_' . $dates['start'];
                    cache($send_bill_key, $msg, 86400);

                    bs_queue(EmailResult::class, 'send_bill', [
                        'title' => $msgData['title'],
                        'sub_title' => $title,
                        'content' => 'send_bill_leave_msg',
                        'send_bill_key' => $send_bill_key,
                        'user_id' => $v['user_id'],
                        'email' => $email
                    ], time(), 10);//延迟执行

                }

            }
        }
    }

    /**
     * 根据账单类型获取日期范围
     * @param $type
     * @return array
     */
    private function get_dates_by_type($type)
    {
        switch ($type) {
            default:
            case 'day':
                $yesterday = date('Y-m-d', strtotime('-1 day'));
                return ['start' => $yesterday, 'end' => $yesterday];
            case 'week':
                $week_start = date('Y-m-d', strtotime('-7 day'));
                $week_end = date('Y-m-d', strtotime('yesterday'));
                return ['start' => $week_start, 'end' => $week_end];
            case 'month':
                $month_start = date('Y-m-01', strtotime('-1 month'));
                $month_end = date('Y-m-01');
                return ['start' => $month_start, 'end' => $month_end];
            case 'year':
                $year_start = date('Y-01-01', strtotime('-1 year'));
                $year_end = date('Y-12-31', strtotime($year_start));
                return ['start' => $year_start, 'end' => $year_end];
        }
    }

    /**
     * 计算同比增长率
     * @param $model
     * @param $v
     * @param $dates
     * @param $type
     * @param $br
     */
    private function calculate_growth($model, &$v, $dates, $type)
    {
        $field = 'type,user_id,sum(IF(type=10,amount,0)) as income,sum(IF(type=20,amount,0)) as outcome';
        $where = [['user_id', '=', $v['user_id']]];
        $stime = $this->get_comparison_date_start($type, $dates);
        $etime = $this->get_comparison_date_end($type, $dates);
        if ($type == 'day') {
            $where[] = ['date', '=', $stime];
        } else {
            $where[] = ['date', 'between', [$stime, $etime]];
        }
        // 获取同期数据
        $cashflows = $model->data_get($where, $field);
        $v['last_income'] = !empty($cashflows['income']) ? $cashflows['income'] : '0.00';
        $v['last_outcome'] = !empty($cashflows['outcome']) ? $cashflows['outcome'] : '0.00';

        $income_rate = $outcome_rate = '0';
        if ($cashflows) {
            //计算增长率
            $income_rate = $cashflows['income'] > 0 ? round(($v['income'] - $cashflows['income']) / $cashflows['income'] * 100, 2) : '0';
            $outcome_rate = $cashflows['outcome'] > 0 ? round(($v['outcome'] - $cashflows['outcome']) / $cashflows['outcome'] * 100, 2) : '0';

            if ($cashflows['income'] == 0 && $v['income'] > 0) {
                $income_rate = '100';
            } elseif ($cashflows['outcome'] == 0 && $v['outcome'] > 0) {
                $outcome_rate = '100';
            }
        }
        $v['income_rate'] = $income_rate . '%';
        $v['outcome_rate'] = $outcome_rate . '%';
    }

    /**
     * 获取对比日期的开始
     * @param $type
     * @param $dates
     * @return string
     */
    private function get_comparison_date_start($type, $dates)
    {
        switch ($type) {
            default:
            case 'day':
                return date('Y-m-d', strtotime('-2 day'));
            case 'week':
                return date('Y-m-d', strtotime('-13 day'));
            case 'month':
                return date('Y-m-01', strtotime('-2 month'));
            case 'year':
                return date('Y-01-01', strtotime("- 1 year", strtotime($dates['start'])));
        }
    }

    /**
     * 获取对比日期的结束
     * @param $type
     * @param $dates
     * @return string
     */
    private function get_comparison_date_end($type, $dates)
    {
        switch ($type) {
            default:
            case 'day':
                return date('Y-m-d', strtotime('-1 day'));
            case 'week':
                return date('Y-m-d', strtotime('-7 day'));
            case 'month':
                return date('Y-m-d', strtotime("+ 1 month", strtotime($this->get_comparison_date_start($type, $dates))));
            case 'year':
                return date('Y-12-31', strtotime("-1 year", strtotime($dates['end'])));
        }
    }

    /**
     * 构建推送消息
     * @param $v
     * @param $dates
     * @param $title
     * @param $br
     * @return string
     */
    private function build_message($v, $dates, $title, $type)
    {
        if ($type == 'day') {
            $times = $dates['start'];
        } else {
            $times = $dates['start'] . '~' . $dates['end'];
        }
        $str = '<div style="margin: 10px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; background-color: #fff; font-family: Arial, sans-serif;">
    <div style="font-size: 18px; color: #333; border-bottom: 1px solid #eee; padding-bottom: 5px; margin-bottom: 10px;">账单详情</div>
    <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
        <span style="color: #555;">日期：</span><strong style="color: #333; font-weight: bold;">' . $times . '</strong>
    </div>
    <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
        <span style="color: #555;">收入(元)：</span><strong style="color: red; font-weight: bold;">￥ ' . $v['income'] . '</strong>
    </div>
    <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
        <span style="color: #555;">支出(元)：</span><strong style="color: red; font-weight: bold;">￥ ' . $v['outcome'] . '</strong>
    </div>
    <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
        <span style="color: #555;">收支差额：</span><strong style="color: red; font-weight: bold;">￥ ' . ($v['income'] - $v['outcome']) . '</strong>
    </div>
    <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
        <span style="color: #555;">同期收支差额(元)：</span><strong style="color: red; font-weight: bold;">￥ ' . ($v['last_income'] - ($v['last_outcome'] ?? 0)) . '</strong>
    </div>
    <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
        <span style="color: #555;">收入同比：</span><strong style="color: red; font-weight: bold;">' . $v['income_rate'] . '</strong>
    </div>
    <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
        <span style="color: #555;">支出同比：</span><strong style="color: red; font-weight: bold;">' . $v['outcome_rate'] . '</strong>
    </div>
</div>';
        return $str;
    }
}
